﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace SPM.DAL
{
    public abstract class DataAccessObject<TDto>
        where TDto: class, SPM.DTL.IDataTransferObject, new()
    {
        public virtual void AddItem(TDto newItem)
        {
            IDbCommand command = CreateInsertCommand(newItem);
            try
            {
                command.Connection.Open();
                command.ExecuteNonQuery();
            }
            finally
            {
                command.Dispose();
            }
        }

        public virtual void UpdateItem(int itemId, TDto newItemData)
        {
            IDbCommand command = CreateUpdateCommand(itemId, newItemData);
            try
            {
                command.Connection.Open();
                command.ExecuteNonQuery();
            }
            finally
            {
                command.Dispose();
            }
        }

        public virtual void DeleteItem(int itemId)
        {
            IDbCommand command = CreateDeleteCommand(itemId);
            try
            {
                command.Connection.Open();
                command.ExecuteNonQuery();
            }
            finally
            {
                command.Dispose();
            }
        }

        public virtual void DeleteItem(TDto item)
        {
            DeleteItem(item.Id);
        }

        public TDto GetItem(int itemId)
        {
            IDbCommand command = CreateGetByPKCommand(itemId);
            try
            {
                command.Connection.Open();
                IDataReader reader = command.ExecuteReader();
                if (reader.Read())
                {
                    TDto item = new TDto();
                    FillDto(reader, item);
                    return item;
                }
                else
                    return null;
            }
            finally
            {
                command.Dispose();
            }
        }

        public virtual IList<TDto> GetAll()
        {
            IDbCommand command = CreateGetAllCommand();
            try
            {
                command.Connection.Open();
                IDataReader reader = command.ExecuteReader();
                List<TDto> result = new List<TDto>();
                while (reader.Read())
                {
                    TDto item = new TDto();
                    FillDto(reader, item);
                    result.Add(item);
                }

                return result;
            }
            finally
            {
                command.Dispose();
            }
        }

        //Rafael: Alterei de "{0}Id" para "id{0}"
        protected virtual IDbCommand CreateDeleteCommand(int id)
        {
            string commandText = String.Format(
                "DELETE FROM {0} where id{0} = {1}",
                TableName,
                id);

            return factory.CreateCommand(commandText);
        }

        //Rafael: Alterei de "{0}Id" para "id{0}"
        protected virtual IDbCommand CreateGetByPKCommand(int id)
        {
            string commandText = String.Format(
                "SELECT * FROM {0} where id{0} = {1};",
                TableName,
                id);

            return factory.CreateCommand(commandText);
        }

        protected virtual IDbCommand CreateGetAllCommand()
        {
            return factory.CreateCommand("SELECT * FROM " + TableName);
        }

        public virtual int GetLastIdentity()
        {
            return factory.GetLastIdentity(this.TableName);
        }

        protected DataFactory factory = new DataFactory();

        internal abstract void FillDto(IDataReader reader, TDto item);

        public abstract string TableName { get; }

        protected abstract IDbCommand CreateUpdateCommand(int id, TDto newData);

        protected abstract TDto CreateItemFromReader(IDataReader reader);

        protected abstract IDbCommand CreateInsertCommand(TDto item);

    }
}
